package com.zjj.algorithm.learning.dmsxl.dynamicplan;


import com.zjj.algorithm.learning.dmsxl.tree.TreeNode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 337. 打家劫舍 III 中档题
 * <p>
 * 小偷又发现了一个新的可行窃的地区。这个地区只有一个入口，我们称之为 root 。
 * <p>
 * 除了 root 之外，每栋房子有且只有一个“父“房子与之相连。一番侦察之后，聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 两个直接相连的房子在同一天晚上被打劫 ，房屋将自动报警。
 * <p>
 * 给定二叉树的 root 。返回 在不触动警报的情况下 ，小偷能够盗取的最高金额 。
 * <p>
 * <p>
 * <p>
 * 示例 1:
 * <p>
 * <p>
 * <p>
 * 输入: root = [3,2,3,null,3,null,1]
 * 输出: 7
 * 解释: 小偷一晚能够盗取的最高金额 3 + 3 + 1 = 7
 * 示例 2:
 * <p>
 * <p>
 * <p>
 * 输入: root = [3,4,5,1,3,null,1]
 * 输出: 9
 * 解释: 小偷一晚能够盗取的最高金额 4 + 5 = 9
 * <p>
 * <p>
 * 提示：
 * <p>
 * 树的节点数在 [1, 104] 范围内
 * 0 <= Node.val <= 104
 *
 * @author zjj_admin
 * @date 2023/2/2 10:11
 */
public class DynamicPlan_31_HouseRobber3 {

    public static void main(String[] args) {

        TreeNode node1 = new TreeNode(3);
        TreeNode node2 = new TreeNode(2);
        TreeNode node3 = new TreeNode(3);
        TreeNode node4 = new TreeNode(3);
        TreeNode node5 = new TreeNode(1);
        TreeNode node6 = new TreeNode(6);
        TreeNode node7 = new TreeNode(7);

        node1.left = node2;
        node1.right = node3;
        node2.right = node4;
        node3.right = node5;

        int res = rob(node1);
        System.out.println("res = " + res);

    }


    /**
     * 思路：本题的房子布局为一颗二叉树，所以可以根据二叉树的搜索方式来判断当前房间是不是应该被偷。
     * 很明显，采用二叉树中序序方式搜索方式最优
     * todo 此方法有错
     *
     * @param root
     * @return
     */
    public static int rob(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        midOrder(root, list);
        int[] nums = new int[list.size()];
        for (int i = 0; i < list.size(); i++) {
            nums[i] = list.get(i);
        }
        int res = rob(nums);
        return res;
    }


    /**
     * 将树中的数据按照中序排列的方式添加到一个list集合中
     *
     * @param root
     * @param list
     */
    public static void midOrder(TreeNode root, List<Integer> list) {
        if (root.left != null) {
            midOrder(root.left, list);
        }
        list.add(root.val);
        if (root.right != null) {
            midOrder(root.right, list);
        }
    }

    /**
     * 根据数组来决定
     *
     * @param nums
     * @return
     */
    public static int rob(int[] nums) {
        if (nums == null) {
            return 0;
        }
        if (nums.length == 1) {
            return nums[0];
        }
        int[] dp = new int[nums.length];
        dp[0] = nums[0];
        if (nums[1] > nums[0]) {
            dp[1] = nums[1];
        } else {
            dp[1] = dp[0];
        }
        for (int i = 2; i < nums.length; i++) {
            //这里需要判断是偷当前房间的利润大还是不偷当前房间的利润大
            //需要判断要不要偷当前的房间
            dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
        }
        return dp[nums.length - 1];
    }

}

